/*
 * PhysicalObject.java
 *
 * Created on 20 February 2004, 15:29
 *
 * Copyright 2008 the Desert Labs Project (http://desertlabs.us)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package us.desertlabs.physics;

/**
 * Instances of this class are used to represent objects that exist in some
 * physical space. Most of the other elements of the physics subpackage are
 * based on the idea that instances of <CODE>PhysicalObject</CODE> will
 * ultimately be affected by the calculations being performed. Put very simply,
 * a <CODE>PhysicalObject</CODE> is defined by its <CODE>Mass</CODE>,
 * <CODE>Location</CODE>, and <CODE>Velocity</CODE>.
 *
 * @author Brandon Franklin
 */
public class PhysicalObject {

    /** The mass of the object */
    private Mass mass;

    /** The current location of the object */
    private Location location;

    /** The velocity of the object */
    private Velocity velocity;

    /**
     * Creates a new instance of <CODE>PhysicalObject</CODE> with the
     * specified initial <CODE>Location</CODE> and <CODE>Mass</CODE>, and
     * with no velocity.
     *
     * @param location the initial <CODE>Location</CODE> of the object
     * @param mass the initial <CODE>Mass</CODE> of the object
     * @throws IllegalArgumentException if any of the parameters are invalid
     */
    public PhysicalObject( final Location location, final Mass mass ) {

        setLocation( location );
        setMass( mass );

        // Initialize the velocity
        final Number[] vels = new Number[location.getDimensionality()];
        for( int i = 0; i < vels.length; i++ ) {
            vels[i] = new Integer( 0 );
        }
        setVelocity( new Velocity( vels ) );
    }

    /**
     * Returns the <CODE>Mass</CODE> of this object.
     *
     * @return the <CODE>Mass</CODE> of this object
     */
    final public Mass getMass() {
        return mass;
    }

    /**
     * Sets the <CODE>Mass</CODE> of this object.
     *
     * @param mass the new <CODE>Mass</CODE> of this object
     * @throws IllegalArgumentException if the parameter is null
     */
    final public void setMass( final Mass mass ) {

        // Validate the mass
        if( mass == null ) {
            throw new IllegalArgumentException( "Mass cannot be null." );
        }

        this.mass = mass;
    }

    /**
     * Returns the <CODE>Velocity</CODE> of this object. Changes to the
     * returned object will be reflected in the state of the <CODE>PhysicalObject</CODE>
     * that owns it, so care should be taken.
     *
     * @return the <CODE>Velocity</CODE> of this object
     */
    final public Velocity getVelocity() {
        return velocity;
    }

    /**
     * Sets the <CODE>Velocity</CODE> of this object.
     *
     * @param velocity the new <CODE>Velocity</CODE> of this object
     * @throws IllegalArgumentException if the parameter is null or invalid
     */
    final public void setVelocity( final Velocity velocity ) {

        // Validate the velocity
        if( velocity == null ) {
            throw new IllegalArgumentException( "Velocity cannot be null." );
        } else if( !velocity.isValid() ) {
            throw new IllegalArgumentException( "Velocity is internally invalid." );
        }

        this.velocity = velocity;
    }

    /**
     * Returns the <CODE>Location</CODE> of this object.
     *
     * @return the <CODE>Location</CODE> of this object
     */
    final public Location getLocation() {
        return location;
    }

    /**
     * Sets the <CODE>Location</CODE> of this object.
     *
     * @param location the new <CODE>Location</CODE> of this object
     * @throws IllegalArgumentException if the parameter is null or invalid
     */
    final public void setLocation( final Location location ) {

        // Validate the location
        if( location == null ) {
            throw new IllegalArgumentException( "Location cannot be null." );
        } else if( !location.isValid() ) {
            throw new IllegalArgumentException( "Location is internally invalid." );
        }

        this.location = location;
    }
}
